﻿using Nemerle.Collections;
using Nemerle.Text;
using Nemerle.Utility;

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;

using Nemerle.ComputationExpressions;
using Nemerle.ComputationExpressions.Async;

class AsyncCombination
{
  public static GetHtmlAsync(this request : WebRequest) : Async[string] {
    def end(handler){
      using(def responce = request.EndGetResponse(handler)) {
        StreamReader(responce.GetResponseStream()).ReadToEnd()
      }
    }
    Async.FromBeginEnd(request.BeginGetResponse(_, null), end)
  }
  
  public static WriteAsync(this stream : Stream, data : string) : Async[FakeVoid] {
    def data = Encoding.UTF8.GetBytes(data);
    Async.FromBeginEnd(stream.BeginWrite(data, 0, data.Length, _, null), stream.EndWrite(_))
  }
  
  public Download(from : string, to : string) : Async[FakeVoid] {
    comp async {
      defcomp html = HttpWebRequest.Create(from).GetHtmlAsync();
      using(def stream = FileStream(to, FileMode.CreateNew, FileAccess.Write)) {
        callcomp stream.WriteAsync(html);
      }
    }
  }
  
  public Init() : void {
    _ = Download("http://google.ru", "google.html").Start().Value
  }
  
  // Wraps .Net begin/end async 
  //  methods into monads.
  // May be extracted to a library
  
  // actual composition of 
  // two async methods
}